/*
 *    Copyright (c) 2018-2025, proj All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the proj developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: proj
 */

package com.ykht.proj.coupon.controller.c;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ykht.proj.common.core.util.DistanceUtil;
import com.ykht.proj.common.core.util.R;
import com.ykht.proj.common.log.annotation.SysLog;
import com.ykht.proj.common.security.annotation.Inner;
import com.ykht.proj.coupon.dto.UserExtDto;
import com.ykht.proj.coupon.entity.CnBrand;
import com.ykht.proj.coupon.entity.CnCompany;
import com.ykht.proj.coupon.entity.CnShop;
import com.ykht.proj.coupon.service.CnBrandService;
import com.ykht.proj.coupon.service.CnCompanyService;
import com.ykht.proj.coupon.service.CnShopService;
import com.ykht.proj.coupon.service.CnUserExtService;
import com.ykht.proj.coupon.vo.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;


/**
 * 店铺表
 *
 * @author proj code generator
 * @date 2020-11-16 17:00:21
 */
@RestController
@AllArgsConstructor
@RequestMapping("c/shop")
@Api(value = "cnshop", tags = "c端店铺相关、搜索")
@Slf4j
public class ShopController {
	/**
	 * 门店服务
	 */
	private final CnShopService cnShopService;
	/**
	 * 公司服务
	 */
	private final CnCompanyService cnCompanyService;

	private final CnUserExtService cnUserExtService;

	@ApiOperation(value = "店铺详情", notes = "店铺详情")
	@GetMapping("/{id}")
	public R<ShopDetail> getById(@PathVariable("id") Long id,BaseLonLat baseLonLat) {
		CnShop shop = new CnShop().selectById(id);
		if (null ==shop) return R.failed("门店不存在");
		return R.ok(cnShopService.getShopDetail(id,baseLonLat));
	}


	@ApiOperation(value = "品牌及其品牌下的店铺", notes = "品牌及其品牌下的店铺")
	@GetMapping("/ppgAndShops")
	public R<PpgAndShopsResp> ppgAndShops(Page page, PpgAndShopsReq req) {
		try {
			log.info("->搜索品牌管：{}", JSONUtil.toJsonStr(req));
			return R.ok(cnShopService.ppgAndShops(page, req));
		} catch (Exception e) {
			e.printStackTrace();
			return R.failed();
		}
	}

	@ApiOperation(value = "搜索", notes = "搜索")
	@PostMapping("/search")
	public R<List<SearchResp>> search(@Valid @RequestBody SearchReq searchReq, BindingResult result) {
		try {
			if (result.hasErrors()) return R.failed(result.getAllErrors().get(0).getDefaultMessage());
			log.info("->搜索：{}", JSONUtil.toJsonStr(searchReq));
			return R.ok(cnShopService.search(searchReq));
		} catch (Exception e) {
			e.printStackTrace();
			return R.failed();
		}
	}

	@ApiOperation(value = "推荐商家，全部门店", notes = "推荐商家和适用门店，全部门店")
	@GetMapping("/page")
	public R<IPage<AboutShopVo>> page(Page page, AboutShopReq req) {
		log.info("->门店搜索：{}", JSONUtil.toJsonStr(req));
		return R.ok(cnShopService.aboutShopList(page, req));
	}

	/**
	 * 品牌下的门店列表
	 * 根据有无定位
	 * 无定位 根据优惠券数量排序倒叙和创建时间倒叙
	 *
	 * @param page
	 * @param req
	 * @return
	 */
	@ApiOperation(value = "品牌详情下的门店列表")
	@GetMapping("/aboutMaxCouponShopPage")
	public R<IPage<AboutShopVo>> pin(Page page, AboutShopReq req) {
		try {
			log.info("->品牌下的门店列表：{}", JSONUtil.toJsonStr(req));

			if (StringUtils.isNotEmpty(req.getLatitude())) {
				return R.ok(cnShopService.aboutShopList(page, req));
			}
			//没有经纬度
			return R.ok(cnShopService.aboutMaxCouponShopList(page, req));
		} catch (Exception e) {
			e.printStackTrace();
			return R.failed();
		}
	}

	@PostMapping("shopDetailByIds")
	public IPage<AboutShopVo> shopDetailByIds(@RequestBody AboutShopReq req) {
		return cnShopService.aboutShopList(req.getPage(), req);
	}


	@ApiOperation(value = "优惠券的使用门店", notes = "优惠券的使用门店")
	@GetMapping("/pageByCoupon")
	public R<IPage<AboutShopVo>> pageByCoupon(Page page, @Valid AboutShopByCouponReq req, BindingResult result) {
		try {
			if (result.hasErrors()) return R.failed(result.getAllErrors().get(0).getDefaultMessage());
			log.info("->优惠券的使用门店：{}", JSONUtil.toJsonStr(req));
			return R.ok(cnShopService.pageByCoupon(page, req));
		} catch (Exception e) {
			e.printStackTrace();
			return R.failed();
		}
	}

	/**
	 * 判断用户是否已 绑定 公司或者门店
	 *
	 * @param map 参数
	 * @return R
	 */
	@ApiOperation("判断用户是否已 绑定 公司或者门店")
	@PostMapping("/getBindingResources")
	public R<List<Integer>> getBindingResources(@RequestBody Map<String, Object> map) {
		try {
			log.info("判断用户是否已 绑定 公司或者门店");
			List<Integer> userIdList = (List<Integer>) map.get("userIdList");
			Integer userType = (Integer) map.get("userType");
			Integer parentId = (Integer) map.get("parentId");
			// 已有的用户ID
			List<Integer> loginIdList = new ArrayList<>();
			// userType 0系统管理员 1公司 2品牌 3门店
			if (userType == 3) {
				List<CnShop> shopList = cnShopService.list(new QueryWrapper<CnShop>().lambda()
						.in(CnShop::getLoginId, userIdList)
						.eq(CnShop::getDisplay, 0).eq(CnShop::getBrandId, parentId));
				if (shopList.size() > 0) {
					shopList.stream().forEach(itme -> loginIdList.add(Integer.valueOf(itme.getLoginId().toString())));
					List<Integer> collect = userIdList.stream().filter(item -> !loginIdList.contains(item)).collect(toList());
					return R.ok(collect);
				}
			} else if (userType == 1) {
				List<CnCompany> companyList = cnCompanyService.list(new QueryWrapper<CnCompany>().lambda()
						.in(CnCompany::getLoginId, userIdList));
				if (companyList.size() > 0) {
					companyList.stream().forEach(itme -> loginIdList.add(Integer.valueOf(itme.getLoginId().toString())));
					List<Integer> collect = userIdList.stream().filter(item -> !loginIdList.contains(item)).collect(toList());
					return R.ok(collect);
				}
			}
			return R.ok(userIdList);
		} catch (Exception e) {
			e.printStackTrace();
			return R.failed();
		}
	}

	/**
	 * 后台  用户绑定资源（品牌，门店，公司）
	 *
	 * @param bindingResourcesVo
	 * @return
	 */
	@ApiOperation(value = "用户绑定资源（品牌，门店，公司）")
	@PostMapping("/userBindingResources")
	public R userBindingResources(@RequestBody UserBindingResourcesVo bindingResourcesVo) {
		/**
		 * 注释掉了，修改后因为牵扯到分布式事务，写入service。这个本来应该写在admin服务里，为了不动前端接口，就没用改动接口
		 */
		/*boolean update = false;
		if (bindingResourcesVo.getUserType() == 1) {
			update = cnCompanyService.update(new UpdateWrapper<CnCompany>().lambda()
					.eq(CnCompany::getId, bindingResourcesVo.getId())
					.set(CnCompany::getLoginId, bindingResourcesVo.getLoginId()).set(CnCompany::getBindTime, LocalDateTime.now()));
		} else if (bindingResourcesVo.getUserType() == 2) {
			update = cnBrandService.update(new UpdateWrapper<CnBrand>().lambda()
					.eq(CnBrand::getId, bindingResourcesVo.getId())
					.set(CnBrand::getLoginId, bindingResourcesVo.getLoginId()).set(CnBrand::getBindTime,LocalDateTime.now()));
		} else if (bindingResourcesVo.getUserType() == 3) {
			update = cnShopService.update(new UpdateWrapper<CnShop>().lambda()
					.eq(CnShop::getId, bindingResourcesVo.getId())
					.set(CnShop::getLoginId, bindingResourcesVo.getLoginId()).set(CnShop::getBindTime,LocalDateTime.now()));
		}*/

		UserExtDto userExt = new UserExtDto();
		userExt.setSjId(bindingResourcesVo.getId());
		userExt.setUserType(bindingResourcesVo.getUserType());
		userExt.setUserId(bindingResourcesVo.getLoginId().intValue());
		return cnUserExtService.bindSj(userExt);
	}


	@ApiOperation(value = "根据经纬度获取所有门店的距离升序排序")
	@PostMapping("distanceList")
	public R<List<CnShopDisVo>> distanceList(@RequestBody ShopDisListVo shopDisListVo){
		log.info("->获取远程服务的门店信息:{}",shopDisListVo);
		try {
			return R.ok(cnShopService.distanceList(shopDisListVo));
		} catch (Exception e) {
			e.printStackTrace();
			return R.failed(new ArrayList<>());
		}
	}

}
